# 利用导数求最小值
from sympy import diff,symbols,solve
x = symbols('x')
y = x ** 2 - 3 * x
dx_dy = diff(y,x)
result = solve(dx_dy,x)[0]
print(f"y导数为0时x的值为:{result}")
result2 = y.subs(x,result)
print(f"x为0时，y的值为:{result2}")
# --------------------------------------------------------------- #
# 利用工程逼近法求最小值
from sympy import symbols
x = symbols("x")
y = x ** 2 - 3 * x
x_val = 10
f_last_time = y.subs(x,x_val)
for i in range(0,100000):
    x_val -= 0.01
    f_this_time = y.subs(x, x_val)
    if f_this_time > f_last_time:
        break
    else:
        f_last_time = f_this_time
# x_val, f_last_time = int(x_val,f_last_time)
print(f"x_val:{x_val},f_last_time:{f_last_time}")
# --------------------------------------------------------------- #
# 利用梯度下降法求最小值
import random
from sympy import symbols,diff
a,x = symbols("a x")
y = x ** 2 - 3 * x
r = diff(y,x)
x_val = random.randint(-10,10)
learning_rate = 1e-3
for i in range(0,10000):
    x_val -= r.subs(x,x_val) * learning_rate
result_y = y.subs(x,x_val)
print(f"x_val:{x_val},x为0时y的值:{result_y}")
# --------------------------------------------------------------- #
# 梯度下降求解多元函数最小值
from sympy import diff,symbols
x, y = symbols("x y")
z = x ** 2 + y ** 2 - 2 * x * y
dz_dx = diff(z,x)
dz_dy = diff(z,y)
epochs = 10_0000
learning_rate = 0.1
x_val = random.randint(-10,10)
y_val = random.randint(-10,10)
for _ in range(epochs):
    # 计算当前梯度
    grad_x = dz_dx.subs({x: x_val, y: y_val})
    grad_y = dz_dy.subs({x: x_val, y: y_val})
    # 更新 x 和 y
    x_val -= learning_rate * grad_x
    y_val -= learning_rate * grad_y
# 计算最终的 z 值
result_z = z.subs({x: x_val, y: y_val})
print(f"x_val:{x_val},y_val:{y_val},x和y最小时,z的值为:{result_z}")